﻿using System;
using System.Collections.Generic;
using System.Drawing;
using System.IO;
using System.Text.RegularExpressions;
using System.Windows.Forms;
using com.magickms._db;
using com.magickms.enums;
using com.magickms.model;
using com.magickms.trainig;
using com.magickms.training.opt;
using com.magickms.util;

namespace com.magickms.training
{
    public partial class Traning : Form
    {
        #region 全局变量
        private TrayPtn _trayPtn;
        private MSession _session;
        private EOptions _options;
        #endregion

        #region 构造函数
        public Traning()
        {
            InitializeComponent();

            _formRs = Util.ReShape(0, 0, Width, Height, 2, true);
            this.Region = _formRs;
        }

        public Traning(TrayPtn trayPtn)
        {
            _trayPtn = trayPtn;

            InitializeComponent();

            _formRs = Util.ReShape(0, 0, Width, Height, 2, true);
            this.Region = _formRs;
        }
        #endregion

        #region 重载属性

        public override string Text
        {
            get
            {
                return base.Text;
            }
            set
            {
                base.Text = value;
                LbText.Text = value;
            }
        }

        private void FormPtn_Load(object sender, System.EventArgs e)
        {
            _session = new MSession();

            bgTl = Image.FromFile("png/bgtl.png");
            bgTm = Image.FromFile("png/bgtm.png");
            bgTr = Image.FromFile("png/bgtr.png");

            bgMl = Image.FromFile("png/bgml.png");
            bgMm = Image.FromFile("png/bgmm.png");
            bgMr = Image.FromFile("png/bgmr.png");

            bgBl = Image.FromFile("png/bgbl.png");
            bgBm = Image.FromFile("png/bgbm.png");
            bgBr = Image.FromFile("png/bgbr.png");

            _exitD = Image.FromFile(@"png\exitd.png");
            if (File.Exists(@"png\exite.png"))
            {
                _exitE = Image.FromFile(@"png\exite.png");
            }
            if (File.Exists(@"png\exitp.png"))
            {
                _exitP = Image.FromFile(@"png\exitp.png");
            }

            _hideD = Image.FromFile(@"png\hided.png");
            if (File.Exists(@"png\hidee.png"))
            {
                _hideE = Image.FromFile(@"png\hidee.png");
            }
            if (File.Exists(@"png\hidep.png"))
            {
                _hideP = Image.FromFile(@"png\hidep.png");
            }

            _menuD = Image.FromFile(@"png\menud.png");
            if (File.Exists(@"png\menue.png"))
            {
                _menuE = Image.FromFile(@"png\menue.png");
            }
            if (File.Exists(@"png\menup.png"))
            {
                _menuP = Image.FromFile(@"png\menup.png");
            }

            PbExit.Image = _exitD;
            PbHide.Image = _hideD;
            PbMenu.Image = _menuD;

            ReDraw();

            ShowOptions(EOptions.Default, "");
        }
        #endregion

        #region 窗口殊效
        //private Color _titleColor = Color.FromArgb(169, 212, 109);
        //private Color _borderColor = Color.FromArgb(169, 212, 109);
        //private Color _contentColor = Color.FromArgb(227, 241, 209);
        //private Color _titleColor = Color.FromArgb(234, 234, 234);
        //private Color _borderColor = Color.FromArgb(178, 178, 178);
        //private Color _contentColor = Color.FromArgb(240, 240, 240);
        //private int _titleHeight = 20;
        //private int _borderWidth = 1;

        /// <summary>
        /// 窗口区域
        /// </summary>
        private Region _formRs;
        /// <summary>
        /// 当前背景
        /// </summary>
        private Image _fromBg;

        /// <summary>
        /// 关闭按钮
        /// </summary>
        private Image _exitD;
        private Image _exitE;
        private Image _exitP;

        /// <summary>
        /// 隐藏按钮
        /// </summary>
        private Image _hideD;
        private Image _hideE;
        private Image _hideP;

        /// <summary>
        /// 选项按钮
        /// </summary>
        private Image _menuD;
        private Image _menuE;
        private Image _menuP;

        /// <summary>
        /// 顶部背景
        /// </summary>
        private Image bgTl;
        private Image bgTm;
        private Image bgTr;

        /// <summary>
        /// 中部背景
        /// </summary>
        private Image bgMl;
        private Image bgMm;
        private Image bgMr;

        /// <summary>
        /// 底部背景
        /// </summary>
        private Image bgBl;
        private Image bgBm;
        private Image bgBr;

        /// <summary>
        /// 窗口重绘
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void FormPtn_Paint(object sender, PaintEventArgs e)
        {
            //g.FillRectangle(new SolidBrush(_borderColor), 0, 0, Width, Height);
            //g.FillRectangle(new SolidBrush(_titleColor), _borderWidth, _borderWidth, Width - _borderWidth * 2, _titleHeight);
            //g.FillRectangle(new SolidBrush(_contentColor), _borderWidth, _titleHeight + _borderWidth, Width - _borderWidth * 2, Height - _titleHeight - _borderWidth * 3);
            //this.Region = _formDim;

            e.Graphics.DrawImage(_fromBg, 0, 0);
        }

        private void ReDraw()
        {
            _fromBg = new Bitmap(Width, Height);
            Graphics g = Graphics.FromImage(_fromBg);

            int x = 0;
            int y = 0;
            int w = Width - bgTr.Width;
            DoDraw(g, bgTl, bgTm, bgTr, x, y, w);

            x = 0;
            y += bgTl.Height;
            w = Width - bgMr.Width;
            DoDraw(g, bgMl, bgMm, bgMr, x, y, w);

            int h = Height - bgBl.Height;
            while (y < h)
            {
                x = 0;
                y += bgMl.Height;
                DoDraw(g, bgMl, bgMm, bgMr, x, y, w);
            }

            x = 0;
            y = h;
            w = Width - bgBr.Width;
            DoDraw(g, bgBl, bgBm, bgBr, x, y, w);
        }

        private void DoDraw(Graphics g, Image imgL, Image imgM, Image imgR, int x, int y, int w)
        {
            g.DrawImage(imgL, x, y);

            x += imgL.Width;
            g.DrawImage(imgM, x, y);

            while (x < w)
            {
                x += imgM.Width;
                g.DrawImage(imgM, x, y);
            }

            g.DrawImage(imgR, w, y);
        }

        /// <summary>
        /// 窗口调整大小
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void FormPtn_Resize(object sender, System.EventArgs e)
        {
            this.Region = _formRs;
        }

        #region Menu按钮
        private void PbMenu_MouseEnter(object sender, System.EventArgs e)
        {
            if (_menuE != null)
            {
                PbMenu.Image = _menuE;
            }
        }

        private void PbMenu_MouseLeave(object sender, System.EventArgs e)
        {
            if (_menuE != null)
            {
                PbMenu.Image = _menuD;
            }
        }

        private void PbMenu_MouseDown(object sender, MouseEventArgs e)
        {
            if (_menuP != null)
            {
                PbMenu.Image = _menuP;
            }
        }

        private void PbMenu_MouseUp(object sender, MouseEventArgs e)
        {
            if (_menuE != null)
            {
                PbMenu.Image = _menuE;
            }
        }
        #endregion

        #region Hide按钮
        private void PbHide_MouseEnter(object sender, System.EventArgs e)
        {
            if (_hideE != null)
            {
                PbHide.Image = _hideE;
            }
        }

        private void PbHide_MouseLeave(object sender, System.EventArgs e)
        {
            if (_hideE != null)
            {
                PbHide.Image = _hideD;
            }
        }

        private void PbHide_MouseDown(object sender, MouseEventArgs e)
        {
            if (_hideP != null)
            {
                PbHide.Image = _hideP;
            }
        }

        private void PbHide_MouseUp(object sender, MouseEventArgs e)
        {
            if (_hideE != null)
            {
                PbHide.Image = _hideE;
            }
        }
        #endregion

        #region Exit按钮
        private void PbExit_MouseEnter(object sender, System.EventArgs e)
        {
            if (_exitE != null)
            {
                PbExit.Image = _exitE;
            }
        }

        private void PbExit_MouseLeave(object sender, System.EventArgs e)
        {
            if (_exitE != null)
            {
                PbExit.Image = _exitD;
            }
        }

        private void PbExit_MouseDown(object sender, MouseEventArgs e)
        {
            if (_exitP != null)
            {
                PbExit.Image = _exitP;
            }
        }

        private void PbExit_MouseUp(object sender, MouseEventArgs e)
        {
            if (_exitE != null)
            {
                PbExit.Image = _exitE;
            }
        }
        #endregion

        private void PbMenu_Click(object sender, System.EventArgs e)
        {

        }

        private void PbHide_Click(object sender, System.EventArgs e)
        {
            WindowState = FormWindowState.Minimized;
        }

        private void PbExit_Click(object sender, System.EventArgs e)
        {
            Visible = false;
        }
        #endregion

        #region 窗口移动事件
        private Point _mouseOffset;
        private bool _isMouseDown;
        /// <summary>
        /// 窗口移动事件
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void WinFormMouseMove(object sender, MouseEventArgs e)
        {
            if (!_isMouseDown)
            {
                return;
            }

            var mousePos = MousePosition;
            mousePos.Offset(_mouseOffset);
            Location = mousePos;
        }

        /// <summary>
        /// 鼠标放松事件，用于窗口最后定位
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void WinFormMouseDown(object sender, MouseEventArgs e)
        {
            if (e.Button != MouseButtons.Left)
            {
                return;
            }
            _mouseOffset = new Point(-e.X - 3, -e.Y - 3);
            _isMouseDown = true;
        }

        /// <summary>
        /// 鼠标压下事件，用于窗口移动判断
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void WinFormMouseUp(object sender, MouseEventArgs e)
        {
            //修改鼠标状态isMouseDown的值
            //确保只有鼠标左键按下并移动时，才移动窗体
            if (e.Button == MouseButtons.Left)
            {
                _isMouseDown = false;
            }
        }
        #endregion

        #region 用户事件
        private void BtSend_Click(object sender, System.EventArgs e)
        {
            string text = TbText.Text;
            TbText.Focus();
            if (string.IsNullOrEmpty(text))
            {
                ShowNotice("不能发送空的消息！");
                return;
            }
            text = Regex.Replace(text, "\r\n?", "\n");

            #region Append Question
            if (_options == EOptions.AppendQuestion)
            {
                MSentence question = new MSentence();
                question.P3100102 = _session.Style;
                question.P3100104 = _session.Language;
                question.P3100105 = _session.RawInput;
                question.P3100106 = Trim(_session.RawInput);
                DBA1000.SaveSentence(question);
                _session.Question.Add(question);
                _session.QIndex = _session.Question.Count - 1;

                MSentence response = DBA1000.FindSentence(text);
                if (response == null)
                {
                    response = new MSentence();
                    response.P3100102 = _session.Style;
                    response.P3100104 = _session.Language;
                    response.P3100105 = text;
                    response.P3100106 = Trim(text);
                    DBA1000.SaveSentence(response);
                }
                _session.Response.Add(response);
                //_session.RIndex = _session.Response.Count - 1;

                DBA1000.AppendResponse(question.P3100103, response.P3100103);
                TbText.Text = "";
                ShowOptions(EOptions.UpdateCategory, "给您的回答加个标签吧！");
                return;
            }
            #endregion

            #region Update Question
            if (_options == EOptions.UpdateQuestion)
            {
                MSentence question = _session.Question[_session.QIndex];
                question.P3100105 = text;
                DBA1000.SaveSentence(question);

                TbText.Text = "";
                ShowOptions(EOptions.Default, "谢谢您的更新，$robot_name$会做得更好！");
                return;
            }
            #endregion

            #region Append Response
            if (_options == EOptions.AppendResponse)
            {
                MSentence question = _session.Question[0];

                MSentence response = DBA1000.FindSentence(MSentence.Encode(text));
                if (response == null)
                {
                    response = new MSentence();
                    response.P3100102 = _session.Style;
                    response.P3100104 = _session.Language;
                    response.P3100105 = text;
                    response.P3100106 = Trim(text);
                    DBA1000.SaveSentence(response);
                }
                else
                {
                    DBA1000.RemoveResponse(question.P3100103, response.P3100103);
                }
                _session.Response.Add(response);
                //_session.RIndex = _session.Response.Count - 1;

                DBA1000.AppendResponse(question.P3100103, response.P3100103);
                TbText.Text = "";
                ShowOptions(EOptions.UpdateCategory, "给您的回答加个标签吧！");
                return;
            }
            #endregion

            #region Update Response
            if (_options == EOptions.UpdateResponse)
            {
                MSentence response = _session.Response[_session.RIndex];
                response.P3100105 = text;
                DBA1000.SaveSentence(response);

                TbText.Text = "";
                ShowOptions(EOptions.Default, "谢谢您的更新，$robot_name$会做得更好！");
                return;
            }
            #endregion

            #region Update Category
            if (_options == EOptions.UpdateCategory)
            {
                string[] arr = text.Split(' ');
                if (arr.Length < 1)
                {
                    return;
                }

                List<MCategory> catList = DBA1000.SaveCategory(arr);
                DBA1000.SaveTags(_session.Response[_session.Response.Count - 1].P3100103, catList);
                TbText.Text = "";
                ShowOptions(EOptions.AppendResponse, "还有其它候选回答吗？您可继续输入哟！");
                return;
            }
            #endregion

            _session.RawInput = text;
            SetAsnwerText("我：" + text);
            TbText.Text = "";

            if (string.IsNullOrEmpty(Trim(text)))
            {
                SendMessage(text);
                return;
            }

            #region 正常问答
            // 查询提问
            _session.Question.Clear();
            _session.QIndex = 0;
            DBA1000.FindQuestion(_session.Question, text, _session.Style, _session.Language, _session.Category);
            if (_session.Question.Count < 1)
            {
                ShowOptions(EOptions.AppendQuestion, "无法回答您的提问，教一下$robot_name$吧？");
                return;
            }

            // 查询应答
            _session.Response.Clear();
            _session.RIndex = 0;
            DBA1000.FindResponse(_session.Response, _session.Question[0].P3100103, _session.Style, _session.Language, _session.Category);
            if (_session.Response.Count < 1)
            {
                ShowOptions(EOptions.AppendResponse, "无法回答您的提问，教一下$robot_name$吧？");
                return;
            }
            #endregion

            SendMessage(_session.Response[_session.RIndex].P3100105);
            ShowOptions(EOptions.RateInfo, "您觉得这个回答怎么样？");
        }

        public void PrevResponse()
        {
            if (_session.RIndex < 1)
            {
                ShowNotice("已经是第一个回答了！");
                return;
            }
            ShowNotice("第" + _session.RIndex + "个回答！");
            _session.RIndex -= 1;
            SetAsnwerText("$robot_name$：" + _session.Response[_session.RIndex].P3100105);
        }

        public void NextResponse()
        {
            if (_session.RIndex > _session.Response.Count - 2)
            {
                ShowNotice("已经是最后一个回答了！");
                return;
            }
            _session.RIndex += 1;
            ShowNotice("第" + _session.RIndex + "个回答！");
            SetAsnwerText("$robot_name$：" + _session.Response[_session.RIndex].P3100105);
        }

        public void RemoveResponse()
        {
            DBA1000.RemoveResponse(_session.Question[_session.QIndex].P3100103, _session.Response[_session.RIndex].P3100103);
            ShowOptions(EOptions.Default, "输入一个问，看$robot_name$回答的怎么样：");
        }

        public void UpdateResponse(int rate)
        {
            DBA1000.UpdateResponse(_session.Question[_session.QIndex].P3100103, _session.Response[_session.RIndex].P3100103, rate);
        }

        public void AppendResponse(string qId, string aId)
        {
            DBA1000.AppendResponse(qId, aId);
        }

        public void ChangeLanguage(string lanId)
        {
            _session.Language = lanId;
        }

        public void ChangeStyle(EStyle style)
        {
            _session.Style = style;
        }
        #endregion

        #region IManTarget 成员

        public void Start()
        {
            if (WindowState != FormWindowState.Normal)
            {
                WindowState = FormWindowState.Normal;
            }
            if (!Visible)
            {
                Visible = true;
            }
        }

        public new void Close()
        {
            Visible = false;
        }

        public void SendMessage(string text)
        {
            SetAsnwerText("$robot_name$：" + text);
        }

        public void ShowWarning(string text)
        {
            MessageBox.Show(this, text, "提示", MessageBoxButtons.YesNo, MessageBoxIcon.Warning);
        }

        public DialogResult ShowConfirm(string text)
        {
            return MessageBox.Show(this, text, "确认", MessageBoxButtons.YesNo, MessageBoxIcon.Question);
        }

        public void ShowNotice(string notice)
        {
            SetNoticeText(notice);
        }

        private Dictionary<EOptions, IOptions> _ucList;
        public void ShowOptions(EOptions options, string notice)
        {
            SetNoticeText(notice);

            if (_ucList == null)
            {
                _ucList = new Dictionary<EOptions, IOptions>();
            }
            IOptions control;
            if (_ucList.ContainsKey(options))
            {
                control = _ucList[options];
            }
            else
            {
                switch (options)
                {
                    case EOptions.Default:
                        control = new BaseInfo(this);
                        _ucList[options] = control;
                        break;
                    case EOptions.Opinions:
                        control = new Opinions(this);
                        _ucList[options] = control;
                        break;
                    case EOptions.RateInfo:
                        control = new RateInfo(this);
                        _ucList[options] = control;
                        break;
                    case EOptions.AppendQuestion:
                        control = new Question(this);
                        _ucList[options] = control;
                        _ucList[EOptions.UpdateQuestion] = control;
                        break;
                    case EOptions.UpdateQuestion:
                        control = new Question(this);
                        _ucList[options] = control;
                        _ucList[EOptions.AppendQuestion] = control;
                        break;
                    case EOptions.AppendResponse:
                        control = new Response(this);
                        _ucList[options] = control;
                        _ucList[EOptions.UpdateResponse] = control;
                        break;
                    case EOptions.UpdateResponse:
                        control = new Response(this);
                        _ucList[options] = control;
                        _ucList[EOptions.AppendResponse] = control;
                        break;
                    case EOptions.UpdateCategory:
                        control = new Category(this);
                        _ucList[options] = control;
                        break;
                    default:
                        return;
                }
                control.Init();
            }

            _options = options;
            ShowControl(control);

            MSentence question = _session.Question.Count > 0 ? _session.Question[_session.QIndex] : null;
            MSentence response = _session.Response.Count > 0 ? _session.Response[_session.RIndex] : null;
            control.ReInit(question, response);
            if (options == EOptions.Default)
            {
                TbText.Text = "";
                return;
            }
            if (options == EOptions.UpdateQuestion)
            {
                TbText.Text = question.P3100105;
                return;
            }
            if (options == EOptions.UpdateResponse)
            {
                TbText.Text = response.P3100105;
                return;
            }
        }

        public delegate void SetTextHandler(string text);
        private void SetAsnwerText(string text)
        {
            if (RbText.InvokeRequired)
            {
                RbText.Invoke(new SetTextHandler(SetAsnwerText), new object[] { text });
            }
            else
            {
                if (!string.IsNullOrEmpty(RbText.Text))
                {
                    RbText.AppendText(Environment.NewLine);
                }
                RbText.AppendText(MSentence.Decode(text));
                RbText.ScrollToCaret();
            }
        }

        private void SetNoticeText(string text)
        {
            if (TbNote.InvokeRequired)
            {
                TbNote.Invoke(new SetTextHandler(SetNoticeText), new object[] { text });
            }
            else
            {
                TbNote.Text = MSentence.Decode(text);
            }
        }

        public delegate void RelayoutHandler(IOptions options);
        private void ShowControl(IOptions options)
        {
            if (PlMisc.InvokeRequired)
            {
                PlMisc.Invoke(new RelayoutHandler(ShowControl), new object[] { options });
            }
            else
            {
                PlMisc.Controls.Clear();

                UserControl uc = options.GetControl();
                uc.AutoSize = true;
                uc.Dock = System.Windows.Forms.DockStyle.Fill;
                uc.Location = new System.Drawing.Point(0, 0);
                uc.Size = new System.Drawing.Size(272, 26);
                uc.TabIndex = 1;
                PlMisc.Controls.Add(uc);
            }
        }

        public bool IsTraining { get; set; }
        #endregion

        public static string Trim(string text)
        {
            return Regex.Replace(Regex.Replace(text, "[^\\w]+", ""), "[_]+", "");
        }
    }
}
